(function() {
    var noneGame = {
        run: function(stage) {
            stage.set("text", "Please select a game on your iOS device.");
        }
    };
    var loadGame = {
        run: function(stage) {
            stage.set("text", "Please wait, the game is loading.");
        }
    };
    var unknownGame = {
        run: function(stage) {
            stage.set("text", "Unknown game.");
        }
    };
    this.GameLoader = new Class({
        available: ["none", "loading"],
        games: {
            "none": noneGame,
            "loading": loadGame
        },
        running: noneGame,
        prefix: "computer/games/",
        suffix: ".js",
        initialize: function(games) {
            this.available = this.available.append(Array.from(arguments));
            GameLoader.addGameData = this.data.bind(this);
            var addSocketEvents = (function() {
                socket.addEvents({
                    message: (function(e) {
                        var message = e.data;
                        if(message == "/Unpaired") {
                            this.interrupt();
                        } else if(message == "/Paired") {
                            this.resume();
                        } else if(message == "$unload") {
                            this.stop();
                        } else if(message.indexOf("$load:") == 0) {
                            this.start(message.substr(6));
                        } else if(message.indexOf("/") != 0 && message.indexOf("$") != 0) {
                            this.message(message);
                        }
                    }).bind(this),
                    close: (function() {
                        this.interrupt();
                    }).bind(this)
                });
            }).bind(this);
            addSocketEvents();
            window.addEvent("domready", (function() {
                document.id("reconnect").addEvent("click", addSocketEvents);
            }).bind(this));
        },
        stop: function() {
            if("stop" in this.running) {
                this.running.stop();
            }
            this.run("none");
        },
        start: function(game) {
            if("stop" in this.running) {
                this.running.stop();
                this.run("loading");
            }
            this.load(game);
        },
        interrupt: function() {
            if("interrupt" in this.running) {
                this.running.interrupt();
            }
        },
        resume: function() {
            if("resume" in this.running) {
                this.running.resume();
            }
            this.startSensors();
        },
        message: function(message) {
            if("message" in this.running) {
                this.running.message(JSON.decode(message, true));
            }
        },
        load: function(game) {
            if(this.available.contains(game)) {
                if(!(game in this.games)) {
                    var element = new Element("script", {
                        src: this.prefix + game.toLowerCase() + this.suffix
                    });
                    document.id(document.head).grab(element);
                } else {
                    this.run(game);
                }
            } else {
                this.run(unknownGame);
            }
        },
        data: function(game, data) {
            if(this.available.contains(game)) {
                this.games[game] = data;
                this.run(game);
            }
        },
        run: function(game) {
            window.addEvent("domready", (function() {
                this.running = this.games[game];
                this.running.run(document.id("stage"));
                this.startSensors();
            }).bind(this));
        },
        startSensors: function() {
            var sensors = this.running.sensors;
            socket.send("$sensors:" + JSON.encode(sensors));
        /*
             * Sensors:
             * - accelerationX*
             * - accelerationY*
             * - accelerationZ*
             * - accelerationIncludingGravityX*
             * - accelerationIncludingGravityY*
             * - accelerationIncludingGravityZ*
             * - rotationRateAlpha*
             * - rotationRateBeta*
             * - rotationRateGamma*
             * - orientationAlpha
             * - orientationBeta
             * - orientationGamma
             *
             * *=not implemented
             */
        }
    });
})();